package file_tab

import (
	"fmt"

	"github.com/samber/lo"
	"github.com/spf13/cast"

	"file_explorer/common/log"
	"file_explorer/model"
	"file_explorer/service"
	"file_explorer/view/components/main_panel/file_tab/filter"
	"file_explorer/view/packed_widgets"
	"file_explorer/view/store"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
)

type FilterWindow struct {
	fyne.Window

	tabCtx *store.FileTabContext

	selectEntry     *widget.SelectEntry
	recursionFilter *filter.RecursionFilter

	ruleMap map[string]*model.FilterRule

	visible bool
}

func (fw *FilterWindow) Toggle() {
	if fw.visible {
		fw.Hide()
		log.Info("过滤器窗口隐藏，路径：%s", fw.tabCtx.GetPath())
	} else {
		fw.Show()
		log.Info("过滤器窗口开启，路径：%s", fw.tabCtx.GetPath())
	}
	fw.visible = !fw.visible
}

func (fw *FilterWindow) OnChange() {
	log.Info("过滤规则变更，路径：%s", fw.tabCtx.GetPath())
	fw.tabCtx.Depth = fw.recursionFilter.GetDepth()
	fw.tabCtx.RefreshPath()
}

func (fw *FilterWindow) Reset() {
	log.Info("过滤规则重置，路径：%s", fw.tabCtx.GetPath())

	fw.selectEntry.Text = ""
	fw.selectEntry.Refresh()

	for _, ft := range fw.tabCtx.Filters {
		ft.Reset()
	}

	fw.recursionFilter.Reset()
	fw.SetTitle(fmt.Sprintf("过滤器: %v", fw.tabCtx.GetDirName()))
}

// 读取规则配置，构造规则下拉框内容
func (fw *FilterWindow) buildKeySelectEntry() *widget.SelectEntry {
	existRules := service.ReadFilterRules()
	fw.ruleMap = make(map[string]*model.FilterRule)
	keys := make([]string, 0, len(existRules))
	for _, rule := range existRules {
		fw.ruleMap[rule.Key] = rule
		keys = append(keys, rule.Key)
	}

	return widget.NewSelectEntry(keys)
}

func (fw *FilterWindow) buildCommonForm() fyne.CanvasObject {
	// 创建filters
	fileNameFilter := filter.NewFileNameFilter(fw.OnChange)
	fileTypeFilter := filter.NewFileTypeFilter(fw.OnChange)
	maxSizeFilter := filter.NewMaxSizeFilter(fw.tabCtx, fw.OnChange)
	minSizeFilter := filter.NewMinSizeFilter(fw.tabCtx, fw.OnChange)
	fw.recursionFilter = filter.NewRecursionFilter(fw.OnChange)

	// 加入filter列表
	fw.tabCtx.Filters = append(fw.tabCtx.Filters, fileNameFilter)
	fw.tabCtx.Filters = append(fw.tabCtx.Filters, fileTypeFilter)
	fw.tabCtx.Filters = append(fw.tabCtx.Filters, maxSizeFilter)
	fw.tabCtx.Filters = append(fw.tabCtx.Filters, minSizeFilter)

	// 创建规则表单
	fw.selectEntry = fw.buildKeySelectEntry()
	commonForm := widget.NewForm(
		widget.NewFormItem("规则名称", fw.selectEntry),
		widget.NewFormItem("文件名", fileNameFilter.GetCanvasObject()),
		widget.NewFormItem("类型", fileTypeFilter.GetCanvasObject()),
		widget.NewFormItem("大小上限", maxSizeFilter.GetCanvasObject()),
		widget.NewFormItem("大小下限", minSizeFilter.GetCanvasObject()),
		widget.NewFormItem("递归深度", fw.recursionFilter.GetCanvasObject()),
	)

	// 规则名下拉框选中后，载入规则配置
	fw.selectEntry.OnChanged = func(key string) {
		rule := fw.ruleMap[key]
		if rule == nil {
			return
		}
		fileNameFilter.LoadValue(cast.ToString(rule.Name))
		fileTypeFilter.LoadValue(rule.Type)
		maxSizeFilter.LoadValue(cast.ToString(rule.MaxSize))
		minSizeFilter.LoadValue(cast.ToString(rule.MinSize))
		fw.recursionFilter.LoadValue(cast.ToString(rule.Depth))
		fw.OnChange()
	}

	// 表单重置，清空输入
	commonForm.CancelText = "重置"
	commonForm.OnCancel = func() {
		fw.Reset()
		fw.OnChange()
	}

	// 表单提交，写入规则配置文件
	commonForm.SubmitText = "保存"
	commonForm.OnSubmit = func() {
		rule := &model.FilterRule{
			Key:     fw.selectEntry.Text,
			Name:    lo.EmptyableToPtr(fileNameFilter.GetValue()),
			Type:    fileTypeFilter.GetValue(),
			MaxSize: lo.EmptyableToPtr(maxSizeFilter.GetValue()),
			MinSize: lo.EmptyableToPtr(minSizeFilter.GetValue()),
			Depth:   lo.EmptyableToPtr(fw.recursionFilter.GetValue()),
		}
		err := service.WriteFilterRule(rule)
		if err != nil {
			packed_widgets.NotifyError("添加过滤规则失败，错误: %v", err)
		}
	}

	return widget.NewCard("通用", "", commonForm)
}

func (fw *FilterWindow) buildTagFilter() fyne.CanvasObject {
	tagFilter := filter.NewFileTagFilter(fw.tabCtx, fw.OnChange)
	fw.tabCtx.Filters = append(fw.tabCtx.Filters, tagFilter)
	return widget.NewCard("标签", "", container.NewScroll(tagFilter.GetCanvasObject()))
}

func newFilterWindow(tabCtx *store.FileTabContext) *FilterWindow {
	window := &FilterWindow{
		tabCtx:  tabCtx,
		visible: true,
		Window:  packed_widgets.NewWindow(fmt.Sprintf("过滤器: %v", tabCtx.GetDirName())),
	}

	window.SetContent(container.NewBorder(
		window.buildCommonForm(),
		nil,
		nil,
		nil,
		window.buildTagFilter(),
	))
	window.Resize(fyne.NewSize(300, 600))
	window.Show()

	return window
}
